/**
 *   Copyright 2008 Alexey Vishentsev
 *
 *   Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *   limitations under the License.
 * 
 */

package com.gwtspreadsheetinput.jsf.component;

import java.util.LinkedList;
import java.util.List;

import javax.faces.model.DataModelEvent;
import javax.faces.model.DataModelListener;

public class SpreadSheetListModel extends SpreadSheetModel {
	
	private List list;
	private int index = -1;
	private Class rowDataBeanClass;
	
	public SpreadSheetListModel(Class rowDataBeanClass){
		this(new LinkedList(),rowDataBeanClass);
	}
	
	public SpreadSheetListModel(List list,
			Class rowDataBeanClass) {
		super();
		setWrappedData(list);
		setRowIndex(-1);
		if (rowDataBeanClass == null) {
			throw new NullPointerException();
		}
		this.rowDataBeanClass = rowDataBeanClass;
	}

	@Override
	public void clearFromCurrentRow() {
		if (list == null) {
			return;
		}
		for(int i = list.size() - 1; i >= 0 && i >= index; i--) {
			list.remove(i);
		}
		for (int i = list.size() - 1; i>=0; i--) {
			if (list.get(i) == null) {
				list.remove(i);
			} else {
				break;
			}	
		}
	}

	@Override
	public void createRowDataObject() {
		if (index < 0 || list == null) {
			return;
		}
		if (index > list.size()) {
			for(int i = list.size(); i < index; i++) {
				list.add(null);
			}
		}
		Object rowDataObject = null;
		try {
			rowDataObject = rowDataBeanClass.newInstance();
		} catch (Exception e) {
			throw new IllegalStateException("Cannot instantiate object of class "
					+ rowDataBeanClass.getName(),e);
		}
		if (index == list.size()) {
			list.add(rowDataObject);
		} else {
			list.set(index, rowDataObject);
		}
	}

	@Override
	public boolean isRowEmpty() {
		if (!isRowAvailable()) {
			return false;
		}
		if (list == null) {
			return false;
		}
		return list.get(index) == null;
	}

	@Override
	public void makeRowEmpty() {
		if (!isRowAvailable() || list == null) {
			return;
		}
		list.set(index, null);
	}

	@Override
	public int getRowCount() {
		if (list == null) {
			return -1;
		} else {
			return list.size();
		}
	}

	@Override
	public Object getRowData() {
		if (list == null) {
			return null;
		} else if (!isRowAvailable()) {
			throw new IllegalArgumentException("Row is not available");
		} else {
			return list.get(index);
		}
	}

	@Override
	public int getRowIndex() {
		return index;
	}

	@Override
	public Object getWrappedData() {
		return list;
	}

	@Override
	public boolean isRowAvailable() {
		if (list == null) {
			return false;
		}
		return index >= 0 && index < list.size();
	}

	@Override
	public void setRowIndex(int rowIndex) {
		if (rowIndex < -1) {
			throw new IllegalArgumentException();
		}
		int oldIndex = index;
		index = rowIndex;
		if (oldIndex == index) {
			return;
		}
		DataModelListener[] listeners = getDataModelListeners();
		if (listeners == null) {
			return;
		}
		DataModelEvent event = new DataModelEvent(this,index,
				isRowAvailable()?getRowData():null);
		for(DataModelListener listener: listeners) {
			if (listener != null) {
				listener.rowSelected(event);
			}
		}
		
	}

	@Override
	public void setWrappedData(Object data) {
		if (data == null) {
            list = null;
            setRowIndex(-1);
        } else {
            list =  (List) data;
            index = -1;
            setRowIndex(0);
        }
		
	}

}
